package com.yue92.datalife.service.impl;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.yue92.datalife.service.ICustomExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
@Slf4j
public class CustomExecutorImpl implements ICustomExecutor, InitializingBean {

    @NacosValue(value = "${core-size:4}", autoRefreshed = true)
    private Integer coreSize;

    @NacosValue(value = "${max-size:16}", autoRefreshed = true)
    private Integer maxSize;

    private ThreadPoolExecutor executor;

    public static class UserThreadFactory implements ThreadFactory {

        private final String namePrefix;
        private final AtomicInteger nextId = new AtomicInteger(1);

        UserThreadFactory(String whatFeatureOfGroup) {
            namePrefix = "From UserThreadFactory's " + whatFeatureOfGroup + "-Worker-";
        }

        @Override
        public Thread newThread(Runnable r) {
            String name = namePrefix + nextId.getAndIncrement();
            Thread thread = new Thread(null, r, name, 0);
            System.out.println(thread.getName());
            return thread;
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("CustomExecutor init: core size: {}, max size: {}", coreSize, maxSize);
        executor = new ThreadPoolExecutor(coreSize, maxSize,
            60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(64),
            new UserThreadFactory("Concurrent"),
            new ThreadPoolExecutor.CallerRunsPolicy());
    }

    @Override
    public void execute(Runnable command) {
        executor.execute(command);
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        return executor.submit(task);
    }

    @Override
    public void setParams(int coreSize, int maxSize) {
        if (executor.getCorePoolSize() != coreSize) {
            executor.setCorePoolSize(coreSize);
            log.info("CustomExecutor core size change to {}", coreSize);
        }
        if (executor.getMaximumPoolSize() != maxSize) {
            executor.setMaximumPoolSize(maxSize);
            log.info("CustomExecutor max size change to {}", maxSize);
        }
    }
}
